#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
# (c) Copyright 2011 - BidiX@BidiX.info
#
#
'''
    url - 
    
    Description : 
 
     Usage :
     
'''
from google.appengine.ext import db
from google.appengine.ext import webapp
from bidix.app import RequestHandler
from HTMLParser import HTMLParser
import urllib
import codecs
import htmlentitydefs

def string_to_tags(str):
    """return a tag array"""
    return str.split(', ')

def tags_to_string(tag_list): 
    return ', '.join(tag_list)


class UrlEntity(db.Model):
    created = db.DateTimeProperty(required=True, auto_now_add=True)
    user = db.UserProperty(auto_current_user_add=True)
    url_name = db.TextProperty()
    url = db.TextProperty()
    tags = db.StringListProperty()
    
    def __init__(self,
               parent=None,
               key_name=None,
               _app=None,
               _from_entity=False,
               **kwds):
        db.Model.__init__(self, **kwds)
             
    @staticmethod
    def get_by_url_name(url_name):
        query = db.Query(UrlEntity)
        query.filter("url_name =", url_name)
        result = query.fetch(1)
        return result[0]
    
    def tag_list(self):
        return string_to_tags(self.tags)
 
    def tags_string(self):
        return tags_to_string(self.tags)
       

class Bookmarks(RequestHandler):
    """a collection of UrlEntity"""

    class Bookmark_Html_parser(HTMLParser):
        """
            For parsing bookmarks file from xmarks.com
            
            DL : Description List
            DT : item définition
            
            DL
                DT
                DT
                ...
                DT
            avec
            DT <H3>{folder_name}</H3>
                DL...
            DT <a href={url}>{url_name}</a>
        """
        def __init__(self, manage_url_fn):
            self.current_tag = ''
            self.tree=[]
            self.manage_url_fn = manage_url_fn
            HTMLParser.__init__(self)
            
        def handle_starttag(self, tag, attrs):
            
            def get_attribute(attrs, name):
                for (attr,value) in attrs:
                    if attr == name:
                        return value
                    
            self.current_tag = tag
            if tag == 'a':
                self.url = get_attribute(attrs, 'href')
                self.url_name = ""
            elif tag =="h3":
                self.folder_name = ""
     
        def handle_endtag(self, tag):
            if tag == 'dl':
                if len(self.tree) > 0:
                    self.tree.pop()
            elif tag == 'h3':
                if (self.folder_name != "Bookmarks Toolbar") and (self.folder_name != "Barre de favoris") and (self.folder_name != "Barre de signets"):
                    self.tree.append(self.folder_name)
            elif tag == 'a':
                if self.url:
                    url_entity = UrlEntity(url=self.url, url_name=self.url_name,tags=self.tree)
                    self.manage_url_fn(url_entity)
            self.current_tag = ''
            
            
        def handle_data(self, data):
            if self.current_tag == 'a':
                decodefn = codecs.getdecoder('utf-8')
                self.url_name += decodefn(data)[0]
            if self.current_tag == 'h3':
                self.folder_name += data
                
        def handle_entityref(self, data):
            str = chr(int(htmlentitydefs.name2codepoint[data]))
            self.handle_data(str)
            
        def handle_charref(self, data):
            str = chr(int(data))
            self.handle_data(str)
 
    def initialize(self, request, response):
        RequestHandler.initialize(self, request, response)
        self.key = self.match.groupdict()['key']
        self.action = self.request.query_string
        
    def delete_all(self):
        where_clause =  self.request.get('where')
        if where_clause:
            self.query = db.GqlQuery("select * from UrlEntity where %s "%where_clause)
        else:
            self.query = db.Query(UrlEntity)
        results = self.query.fetch(10000)
        for r in results:
            r.delete()
        return "All bookmarks deleted"
        
    def format_form(self, key=""):
        if key:
            entity = UrlEntity.get(key)
        else:
            entity = UrlEntity()
            entity.key=""
        self.render({'template':'bookmark_form.html',
                     'url': entity})

    def format_list(self):
        where_clause =  self.request.get('where')
        if where_clause:
            self.query = db.GqlQuery("select * from UrlEntity where %s "%where_clause)
        else:
            self.query = db.Query(UrlEntity)
        urls = self.query.fetch(10000)
        self.render({'template': 'bookmarks_list.html', 'url_list': urls})
    
    def format_load_form(self):
        self.template_file='bookmarks_load.html'
        self.render({'template': 'bookmarks_load.html'})
       
       
    def get(self, *groups):
        if not self.key:
            if self.action == 'load':
                return self.format_load_form()
            if self.action == 'delete':
                return self.delete_all()
            if self.action == 'add':
                return self.format_form('')
            return self.format_list()
        else:
            if self.action == 'go':
                entity = UrlEntity.get_by_url_name(urllib.unquote(self.key.url_decode()))
                if entity:
                    self.response.headers.add_header('Location' , entity.url)
                    self.response.set_status(301)
                    return None
            elif self.action == 'delete':
                entity = UrlEntity.get(self.key)
                if entity:
                    entity.delete()
                    self.response.headers.add_header('Location' , self.app_path)
                    self.response.set_status(301)
                    return None
               
            return self.format_form(self.key)
            
    def load_bookmarks(self):
        def add_url(url):
            url.put()
        html = self.request.get('html')
        parser = Bookmarks.Bookmark_Html_parser(add_url)
        parser.feed(html)
        return "Loaded"
        
    
    def post(self, *args):
        if self.request.get('html'):
            self.load_bookmarks()
            self.action = None
            self.get()
            return
        key = self.request.get('key')
        name = urllib.unquote(self.request.get('name'))
        url = self.request.get('url')
        tag_list = string_to_tags(self.request.get('tags'))
        if key:
            entity = UrlEntity.get(key)
            entity.url_name = name
            entity.url = url
            entity.tags = tag_list
        else:
            entity = UrlEntity(url_name=name, url=url, tags=tag_list)
        entity.put()
        self.key = None
        self.action = None
        self.get()
        
  

            